package com.nefu.softlab.xjwc.service.impl;

import com.nefu.softlab.xjwc.common.Constant;
import com.nefu.softlab.xjwc.mapper.ActivityMapper;
import com.nefu.softlab.xjwc.mapper.RedisMapper;
import com.nefu.softlab.xjwc.mapper.UserMapper;
import com.nefu.softlab.xjwc.model.User;
import com.nefu.softlab.xjwc.service.UserService;
import com.nefu.softlab.xjwc.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author : Ar1es
 * @date : 2020/1/14
 * @since : Java 8
 */
@Service
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;
    private final RedisMapper redisMapper;
    private final LoggerUtil logger;
    private final ActivityMapper activityMapper;
    /**
     * 自动装配 数据源事务管理器
     */
    private final DataSourceTransactionManager dataSourceTransactionManager;

    @Autowired
    public UserServiceImpl(UserMapper userMapper, RedisMapper redisMapper, LoggerUtil logger, ActivityMapper activityMapper, DataSourceTransactionManager dataSourceTransactionManager) {
        this.userMapper = userMapper;
        this.redisMapper = redisMapper;
        this.logger = logger;
        this.activityMapper = activityMapper;
        this.dataSourceTransactionManager = dataSourceTransactionManager;
    }

    /**
     * 自动提交，手动回滚
     * @param user
     * @return
     * @throws XJWCException
     */
    @Override
    @Transactional
    public JSONResult insertUser(User user) throws XJWCException {
        // 配置事务策略
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setName("transaction");
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        // 设置状态点
        TransactionStatus status = dataSourceTransactionManager.getTransaction(def);

        //先查询缓存，未命中再查询数据库
        if (redisMapper.hsize(Constant.USER_PHONE_EXIST) != 0) {
            if (redisMapper.hHasKey(Constant.USER_PHONE_EXIST, user.getPhone())) {
                throw new XJWCException("该号码已被注册，请重试");
            }
        } else {
            int num = userMapper.findByPhone(user.getPhone());
            System.out.println(num);
            if (0 < num) {
                throw new XJWCException("该号码已被注册，请重试");
            }
        }

        String id = GetRandom.getUUID();
        user.setUserId(id);
        user.setRole(2);

        //密码加密存储
        Object o = MD5.MD5(user.getPhone(), user.getPassword());

        user.setPassword(String.valueOf(o));
        try{
            userMapper.insertUser(user);
            userMapper.insertUserRole(id, 2);
            redisMapper.hset(Constant.USER_PHONE_EXIST, user.getPhone(), 1);
            logger.info("添加用户成功" + JsonUtil.getJsonString(user));
        } catch (Exception ex) {
            dataSourceTransactionManager.rollback(status);
            if (redisMapper.hHasKey(Constant.USER_PHONE_EXIST, user.getPhone())) {
                redisMapper.hdel(Constant.USER_PHONE_EXIST, user.getPhone());
            }
            logger.error("添加用户失败 ： " + ex.getMessage());
            throw new XJWCException("添加用户失败，请重新尝试！");
        }
        return JSONResult.ok(1);
    }

    @SuppressWarnings("Duplicates")
    @Override
    @Transactional
    public String addAdmin(User user) throws XJWCException {
        // 配置事务策略
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setName("transaction");
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        // 设置状态点
        TransactionStatus status = dataSourceTransactionManager.getTransaction(def);

        // 先查询缓存，未命中再查询数据库
        if (redisMapper.hsize(Constant.USER_PHONE_EXIST) != 0) {
            if (redisMapper.hHasKey(Constant.USER_PHONE_EXIST, user.getPhone())) {
                throw new XJWCException("该号码已被注册，请重试!");
            }
        } else {
            int num = userMapper.findByPhone(user.getPhone());
            System.out.println("是否已经有当前注册账号(1 表示有，0表示没有) : " + num);
            if (0 < num) {
                throw new XJWCException("该号码已被注册，请重试!");
            }
        }

        String id = GetRandom.getUUID();
        user.setUserId(id);
        user.setRole(1);

        //密码加密存储
        Object o = MD5.MD5(user.getPhone(), user.getPassword());

        user.setPassword(String.valueOf(o));
        try {
            userMapper.insertUser(user);
            userMapper.insertUserRole(id, 1);
            userMapper.insertUserRole(id, 2);
            userMapper.insertUserRole(id, 3);
            redisMapper.hset(Constant.USER_PHONE_EXIST, user.getPhone(), 1);
            logger.info("添加管理员成功, " + JsonUtil.getJsonString(user));
        } catch (Exception ex) {
            ex.printStackTrace();
            dataSourceTransactionManager.rollback(status);
            if (redisMapper.hHasKey(Constant.USER_PHONE_EXIST, user.getPhone())) {
                redisMapper.hdel(Constant.USER_PHONE_EXIST, user.getPhone());
            }
            logger.error("添加管理员失败 ： " + ex.getMessage());
            throw new XJWCException("添加管理员失败，请重新尝试！");
        }
        return "添加管理员成功!";
    }

    @Override
    public int updateUserPassword(User user) throws XJWCException{

        //密码加密存储
        Object o = MD5.MD5(user.getPhone(), user.getPassword());

        user.setPassword(String.valueOf(o));

        int s =  userMapper.updateUserPassword(user);
        if (s == 1) {
            updateRedis();
            return s;
        } else {
            throw new XJWCException("修改失败!");
        }
    }

    @Override
    public int updateUserInfo(User user) throws XJWCException{
        int s = userMapper.updateUserInfo(user);
        if (s == 1) {
            updateRedis();
            return s;
        } else {
            throw new XJWCException("修改失败!");
        }
    }

    @Override
    public List<User> selectAllUser(User user) throws XJWCException {
        List<User> list = userMapper.selectAllUser(user);
        if (null != list) {
            return list;
        } else {
            throw new XJWCException("查询用户失败，请重试");
        }
    }

    @Override
    public List<User> selectUserInfo(User user) throws XJWCException {
        List<User> list = userMapper.selectUserInfo(user);
        if (null != list && 1 == list.size()) {
            return list;
        } else {
            throw new XJWCException("查询用户失败，请重试");
        }
    }

    @Override
    public Object deleteUserById(String userId) throws XJWCException {
        int f = userMapper.deleteUserById(userId);
        if (f == 1) {
            updateRedis();
            return "删除成功!";
        } else {
            throw new XJWCException("删除失败!");
        }
    }

    @Override
    public void updateRedis() {
        List<Integer> idList = activityMapper.selectAllActivityId();
        idList.parallelStream().forEach(i -> {
            if (redisMapper.hasKey(i.toString())) {
                List<Map<String, Object>> list0 = (List<Map<String, Object>>) redisMapper.get(i.toString());
                List<Map<String, Object>> newList0 = new ArrayList<>();
                list0.parallelStream().forEach(map0 -> {
                    Map<String, Object> newMap0 = new HashMap<>();
                    List<User> userList0 = userMapper.selectUserInfo(new User((String)(map0.get("userId"))));
                    if (userList0.size() == 1) {
                        User u = userList0.get(0);
                        newMap0.put("userId", map0.get("userId"));
                        newMap0.put("phone", u.getPhone());
                        newMap0.put("userName", u.getUserName());
                        newMap0.put("unit", u.getUnit());
                        newMap0.put("role", u.getRole());
                        newMap0.put("activity", u.getActivity());
                        newList0.add(newMap0);
                    }
                });
                redisMapper.set(i.toString(), newList0);
            }
        });
    }
}
